#pragma once

#include <iostream>
#include <vector>
#include <queue>
#include <pthread.h>
#include "thread.hpp"
#include "lockguard.hpp"
#include <mutex> //c++ 中也有锁的概念

using namespace ThreadNS;

#define NUM 15

template <class T>
class ThreadPool;

template <class T>
class ThreadData
{
public:
    ThreadData(ThreadPool<T> *tpthis, std::string threadname)
        : _tpthis(tpthis), _threadname(threadname)
    {
    }

    ThreadPool<T> *_tpthis;
    std::string _threadname;
};

template <class T>
class ThreadPool
{
private:
    int _num;
    std::vector<Thread *> _threads; // 保存创建的线程
    std::queue<T> _task_queue;      // 保存任务列表
    pthread_mutex_t _mutex;         // 保护任务队列
    pthread_cond_t _cond;           // 线程阻塞的条件变量

    // 单例
    static ThreadPool<T> *_ptp;
    // 这里的静态指针是，公共资源，在多线程访问的时候可能会出问题，因为后面多线程会对他进行判断。
    // 所以需要对他进行加锁
    static std::mutex _cpplock; // c++的锁

private:
    static void *handlertask(void *args)
    {
        // sleep(3);
        // std::cout<<(args)<<std::endl;
        ThreadData<T> *data = static_cast<ThreadData<T> *>(args);
        while (true)
        {
            // data->_tpthis->lockqueue();
            T t;
            {
                LockGuard lock(data->_tpthis->getmutex());
                while (data->_tpthis->queueempty())
                {
                    data->_tpthis->waitthread();
                }
                t = data->_tpthis->queuepop();
            }
            // data->_tpthis->unlockqueue();
            std::cout << data->_threadname << "处理任务：" << t() << std::endl;
        }
        delete data;
        return nullptr;
    }
    void lockqueue()
    {
        pthread_mutex_lock(&_mutex);
    }
    void unlockqueue()
    {
        pthread_mutex_unlock(&_mutex);
    }
    bool queueempty()
    {
        return _task_queue.empty();
    }
    void waitthread()
    {
        pthread_cond_wait(&_cond, &_mutex);
    }
    T queuepop()
    {
        // 这个是内部接口
        // 不用加锁，因为在锁内部调用。
        T ret = _task_queue.front();
        _task_queue.pop();
        return ret;
    }
    void signalthread()
    {
        pthread_cond_signal(&_cond);
    }

    pthread_mutex_t *getmutex()
    {
        return &_mutex;
    }
    ThreadPool(int num = NUM)
        : _num(num)
    {
        pthread_mutex_init(&_mutex, nullptr);
        pthread_cond_init(&_cond, nullptr);
        for (int i = 0; i < _num; ++i)
        {

            Thread *tp = new Thread();
            _threads.push_back(tp);
        }
    }
    void operator=(const ThreadPool<T> &) = delete;
    ThreadPool(const ThreadPool<T> &) = delete;

public:
    void start()
    {
        for (auto &e : _threads)
        {
            ThreadData<T> *data = new ThreadData<T>(this, e->getname());
            e->start(handlertask, (void *)data);
            // std::cout<<e<<" thread start.."<<std::endl;
        }
    }
    void push(T in)
    {
        // lockqueue();
        LockGuard lock = getmutex();
        _task_queue.push(in);
        std::cout << "收到任务：" << in.totaskstring() << std::endl;
        signalthread();
        // unlockqueue();
    }
    ~ThreadPool()
    {
        pthread_mutex_destroy(&_mutex);
        pthread_cond_destroy(&_cond);
        for (auto &e : _threads)
        {
            e->join();
            delete e;
        }
    }

    // 单例
    static ThreadPool<T> *getinstance(int num = NUM)
    {
        if (_ptp == nullptr)//加上这个可以在对象创建完毕之后，不用再加锁判断即可返回。
        {
            _cpplock.lock(); // c++的加锁
            if (_ptp == nullptr)
            {
                _ptp = new ThreadPool<T>(num);
            }
            _cpplock.unlock(); // c++的解锁
        }
        return _ptp;
    }
};

// 模板中静态成员的初始化
template <class T>
ThreadPool<T> *ThreadPool<T>::_ptp = nullptr;

template <class T>
std::mutex ThreadPool<T>::_cpplock;

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
